package com.whmskj.xjlhbc.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.PatternPool;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ReUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.whmskj.xjlhbc.domain.*;
import com.whmskj.xjlhbc.dto.ScanDto;
import com.whmskj.xjlhbc.mapper.*;
import com.whmskj.xjlhbc.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class ScanServiceImpl implements IScanService {


    @Autowired
    private ThePlanesStrappedToATableMapper thePlanesStrappedToATableMapper;

    @Autowired
    private IRundataInfoService rundataInfoService;

    @Autowired
    private MeszjjMapper meszjjMapper;

    @Autowired
    private MesjsjMapper mesjsjMapper;

    @Autowired
    private IStatisticsService statisticsService;

    @Autowired
    private IStatisticsDayService statisticsDayService;

    @Autowired
    private IStatisticsDayZjService statisticsDayZjService;

    @Autowired
    private IStatisticsDayJsService statisticsDayJsService;

    @Autowired
    private StopdataInfoMapper stopdataInfoMapper;

    @Autowired
    private By01MaintenanceScheduleMapper by01MaintenanceScheduleMapper;

    @Autowired
    private SchedulingOfSbbx01MalfunctionRepMapper schedulingOfSbbx01MalfunctionRepMapper;

    @Autowired
    private MeskyjMapper meskyjMapper;

    @Autowired
    private MesglMapper mesglMapper;

    @Autowired
    private MesjzkMapper mesjzkMapper;

    @Autowired
    private MeszjjLzMapper meszjjLzMapper;

    @Autowired
    private MesjsjLzMapper mesjsjLzMapper;

    @Override
    public ScanDto getDetail(String code) {
        List<String> stationNumber = ReUtil.findAllGroup0(PatternPool.NUMBERS, code);
        List<String> device = ReUtil.findAllGroup0(PatternPool.CHINESES, code);
        if(stationNumber.isEmpty() || device.isEmpty()) return new ScanDto();
        String deviceName = device.get(0);
        String deviceCode = stationNumber.get(0);

        ScanDto result = new ScanDto();
        ScanDto.Info topInfo = result.getTopInfo();
        topInfo.setDeviceCode(deviceCode);
        topInfo.setDeviceName(deviceName);
        topInfo.setUserName(getNameOfPersonnel(deviceCode));
        topInfo.setType(deviceName.equals("织布机") ? 1 :
                deviceName.equals("整经机") ? 2 :
                deviceName.equals("浆纱机") ? 3 :
                deviceName.equals("空压机") ? 4 :
                deviceName.equals("锅炉房") ? 5 :
                deviceName.equals("AGV") ? 6 :
                deviceName.equals("经轴库") ? 7 : 0);

        setRundataInfo(result);
        setClInfo(result);
        setStopInfo(result);
        setWbInfo(result);
        setGzInfo(result);
        setRunInfoList(result);
        return result;
    }

    private String getNameOfPersonnel(String code){
        if(code.length()!= 4)return null;
        int hour = DateUtil.date().hour(true);
        String classes = hour >= 9 && hour < 21 ? "早" : "晚";
        LambdaQueryWrapper<ThePlanesStrappedToATable> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ThePlanesStrappedToATable::getF7ba, DateUtil.today())
                .eq(ThePlanesStrappedToATable::getClasses5, classes)
                .like(ThePlanesStrappedToATable::getF657, code).last("limit 1");
        ThePlanesStrappedToATable thePlanesStrappedToATable = Optional.ofNullable(thePlanesStrappedToATableMapper.selectOne(wrapper)).orElseGet(ThePlanesStrappedToATable::new);
        return thePlanesStrappedToATable.getNameOfPersonnel();
    }

    private void setRunInfoList(ScanDto result){
        List<Object> runInfoList = result.getRunInfoList();
        ScanDto.Info topInfo = result.getTopInfo();
        String deviceCode = topInfo.getDeviceCode();
        int type = topInfo.getType();
        String today = DateUtil.today();
        if(type == 2){//整经机
            LambdaQueryWrapper<MeszjjLz> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(MeszjjLz::getMacid, deviceCode);
            wrapper.eq(MeszjjLz::getDateymd, today);
            wrapper.orderByDesc(MeszjjLz::getTs);
            runInfoList.addAll(meszjjLzMapper.selectList(wrapper));
        }
        if(type == 3){//浆纱机
            LambdaQueryWrapper<MesjsjLz> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(MesjsjLz::getMacid, deviceCode);
            wrapper.eq(MesjsjLz::getDateymd, today);
            wrapper.orderByDesc(MesjsjLz::getTs);
            runInfoList.addAll(mesjsjLzMapper.selectList(wrapper));
        }
        if(type == 4){
            LambdaQueryWrapper<MesKyj> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(MesKyj::getStationNumber, deviceCode);
            runInfoList.addAll(meskyjMapper.selectList(wrapper));
        }
        if(type == 5){
            LambdaQueryWrapper<Mesgl> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Mesgl::getMacid, deviceCode);
            runInfoList.addAll(mesglMapper.selectList(wrapper));
        }
    }
    private void setRundataInfo(ScanDto result){
        ScanDto.Info topInfo = result.getTopInfo();
        int type = topInfo.getType();
        String deviceCode = topInfo.getDeviceCode();
        if(type == 1){//织布机
            LambdaQueryWrapper<RundataInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(RundataInfo::getMacid, deviceCode).last("limit 1");
            RundataInfo rundataInfo = Optional.ofNullable(rundataInfoService.getOne(wrapper)).orElseGet(RundataInfo::new);
            result.setRundataInfo(rundataInfo);
            topInfo.setState(rundataInfo.getLoomstate());
        }
        if(type == 2){//整经机
            LambdaQueryWrapper<Meszjj> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Meszjj::getMacid, deviceCode).last("limit 1");
            result.setRundataInfo(Optional.ofNullable(meszjjMapper.selectOne(wrapper)).orElseGet(Meszjj::new));
        }
        if(type == 3){//浆纱机
            LambdaQueryWrapper<Mesjsj> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Mesjsj::getMacid, deviceCode).last("limit 1");
            result.setRundataInfo(Optional.ofNullable(mesjsjMapper.selectOne(wrapper)).orElseGet(Mesjsj::new));
        }
        if(type == 4){ //空压机
            LambdaQueryWrapper<MesKyj> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(MesKyj::getStationNumber, deviceCode).last("limit 1");
            result.setRundataInfo(Optional.ofNullable(meskyjMapper.selectOne(wrapper)).orElseGet(MesKyj::new));
        }
        if(type == 5){
            LambdaQueryWrapper<Mesgl> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Mesgl::getMacid, deviceCode).last("limit 1");
            result.setRundataInfo(Optional.ofNullable(mesglMapper.selectOne(wrapper)).orElseGet(Mesgl::new));
        }
        if(type == 7){
            LambdaQueryWrapper<Mesjzk> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Mesjzk::getMacid, deviceCode);
            List<Mesjzk> mesjzkList = mesjzkMapper.selectList(wrapper);
            List<Mesjzk> mesjzkList1 = mesjzkList.stream().filter(f -> ReUtil.isMatch(PatternPool.NUMBERS, f.getZc())).collect(Collectors.toList());

            List<String> bhList = mesjzkList1.stream().map(Mesjzk::getBh).distinct().collect(Collectors.toList());
            ScanDto.JzkInfo jzkInfo = new ScanDto.JzkInfo();
            jzkInfo.setBh(bhList.size());
            jzkInfo.setCz(mesjzkList1.size());
            jzkInfo.setZc(mesjzkList1.stream().mapToLong(m->NumberUtil.parseLong(m.getZc(),0L)).sum());
            List<Mesjzk> jzkList = bhList.stream().map(bh -> {
                List<Mesjzk> list = mesjzkList1.stream().filter(f -> f.getBh().equals(bh)).collect(Collectors.toList());
                long zs = list.size();
                long zc = list.stream().mapToLong(m -> NumberUtil.parseLong(m.getZc(), 0L)).sum();
                Mesjzk jzk = new Mesjzk();
                jzk.setBh(bh);
                jzk.setZwh(String.valueOf(zs));
                jzk.setZc(String.valueOf(zc));
                return jzk;
            }).collect(Collectors.toList());

            jzkInfo.getList().addAll(jzkList);
            result.setRundataInfo(jzkInfo);
        }
    }

    private void setClInfo(ScanDto result){
        ScanDto.Info topInfo = result.getTopInfo();
        int type = topInfo.getType();
        String deviceCode = topInfo.getDeviceCode();
        int year = DateUtil.date().year();
        if(type == 1){
            LambdaQueryWrapper<StatisticsDay> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(StatisticsDay::getMacid, deviceCode)
                    .like(StatisticsDay::getDateymd, year);
            List<StatisticsDay> statisticsDayList = statisticsDayService.list(wrapper);
            ScanDto.ClInfo clInfo = result.getClInfo();
            List<String> bzDateList = getBzDateList();
            double bzSum = statisticsDayList.stream().filter(f -> bzDateList.contains(f.getDateymd())).mapToDouble(v -> NumberUtil.parseDouble(v.getClothlength(), 0.0)).sum();
            String month = DateUtil.format(DateUtil.date(), "yyyy-MM");
            double bySum = statisticsDayList.stream().filter(f -> month.equals(f.getDateymd().substring(0,7))).mapToDouble(v -> NumberUtil.parseDouble(v.getClothlength(), 0.0)).sum();
            double bnSum = statisticsDayList.stream().mapToDouble(v -> NumberUtil.parseDouble(v.getClothlength(), 0.0)).sum();
            clInfo.setBz(String.format("%.2f",bzSum));
            clInfo.setBy(String.format("%.2f",bySum));
            clInfo.setBn(String.format("%.2f",bnSum));

            QueryWrapper<Statistics> statisticsLambdaQueryWrapper = new QueryWrapper<>();
            statisticsLambdaQueryWrapper.eq("macid", deviceCode);
            statisticsLambdaQueryWrapper.in("dateymd",bzDateList);
            statisticsLambdaQueryWrapper.select("dateymd","round(sum(clothlength),2)clothlength","round(sum(clothlength_zb),2)clothlength_zb","round(avg(efficiency),2)efficiency");
            statisticsLambdaQueryWrapper.last("group by dateymd");
            List<Statistics> statisticsList = statisticsService.list(statisticsLambdaQueryWrapper);
            clInfo.getClList().addAll(statisticsList);
        }
        if(type == 2){
            LambdaQueryWrapper<StatisticsDayZj> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(StatisticsDayZj::getMacid, deviceCode)
                    .like(StatisticsDayZj::getDateymd, year);
            List<StatisticsDayZj> statisticsDayList = statisticsDayZjService.list(wrapper);
            ScanDto.ClInfo clInfo = result.getClInfo();
            List<String> bzDateList = getBzDateList();
            double bzSum = statisticsDayList.stream().filter(f -> bzDateList.contains(f.getDateymd())).mapToDouble(v -> NumberUtil.parseDouble(v.getClothlength(), 0.0)).sum();
            String month = DateUtil.format(DateUtil.date(), "yyyy-MM");
            double bySum = statisticsDayList.stream().filter(f -> month.equals(f.getDateymd().substring(0,7))).mapToDouble(v -> NumberUtil.parseDouble(v.getClothlength(), 0.0)).sum();
            double bnSum = statisticsDayList.stream().mapToDouble(v -> NumberUtil.parseDouble(v.getClothlength(), 0.0)).sum();
            clInfo.setBz(String.format("%.2f",bzSum));
            clInfo.setBy(String.format("%.2f",bySum));
            clInfo.setBn(String.format("%.2f",bnSum));
        }
        if(type == 3){
            LambdaQueryWrapper<StatisticsDayJs> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(StatisticsDayJs::getMacid, deviceCode)
                    .like(StatisticsDayJs::getDateymd, year);
            List<StatisticsDayJs> statisticsDayList = statisticsDayJsService.list(wrapper);
            ScanDto.ClInfo clInfo = result.getClInfo();
            List<String> bzDateList = getBzDateList();
            double bzSum = statisticsDayList.stream().filter(f -> bzDateList.contains(f.getDateymd())).mapToDouble(v -> NumberUtil.parseDouble(v.getClothlength(), 0.0)).sum();
            String month = DateUtil.format(DateUtil.date(), "yyyy-MM");
            double bySum = statisticsDayList.stream().filter(f -> month.equals(f.getDateymd().substring(0,7))).mapToDouble(v -> NumberUtil.parseDouble(v.getClothlength(), 0.0)).sum();
            double bnSum = statisticsDayList.stream().mapToDouble(v -> NumberUtil.parseDouble(v.getClothlength(), 0.0)).sum();
            clInfo.setBz(String.format("%.2f",bzSum));
            clInfo.setBy(String.format("%.2f",bySum));
            clInfo.setBn(String.format("%.2f",bnSum));
        }
    }

    private void setStopInfo(ScanDto result){
        ScanDto.Info topInfo = result.getTopInfo();
        int type = topInfo.getType();
        if(type != 1) return;
        String deviceCode = topInfo.getDeviceCode();
        LambdaQueryWrapper<StopdataInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StopdataInfo::getMacid,deviceCode);
        StopdataInfo stopdataInfo = Optional.ofNullable(stopdataInfoMapper.selectOne(queryWrapper)).orElseGet(StopdataInfo::new);
        List<ScanDto.StopInfo> stopInfoList = result.getStopInfo();
        ScanDto.StopInfo stopInfo = new ScanDto.StopInfo();
        stopInfo.setType("短纬停");
        stopInfo.setTotal(stopdataInfo.getStopcount_weft_short());
        stopInfo.setStoptime(stopdataInfo.getStoptime_weft_short());
        stopInfoList.add(stopInfo);
        stopInfo = new ScanDto.StopInfo();
        stopInfo.setType("经停");
        stopInfo.setTotal(stopdataInfo.getStopcount_warp());
        stopInfo.setStoptime(stopdataInfo.getStoptime_warp());
        stopInfoList.add(stopInfo);
        stopInfo = new ScanDto.StopInfo();
        stopInfo.setType("长纬停");
        stopInfo.setTotal(stopdataInfo.getStopcount_weft_long());
        stopInfo.setStoptime(stopdataInfo.getStoptime_weft_long());
        stopInfoList.add(stopInfo);
        stopInfo = new ScanDto.StopInfo();
        stopInfo.setType("其它");
        stopInfo.setTotal(stopdataInfo.getStopcount_other());
        stopInfo.setStoptime(stopdataInfo.getStoptime_other());
        stopInfoList.add(stopInfo);
        stopInfo = new ScanDto.StopInfo();
        stopInfo.setType("总计");
        stopInfo.setTotal(stopdataInfo.getStopcount_total());
        stopInfo.setStoptime(stopdataInfo.getStoptime_total());
        stopInfoList.add(stopInfo);
    }

    private void setWbInfo(ScanDto result){
        ScanDto.Info topInfo = result.getTopInfo();
        String deviceCode = topInfo.getDeviceCode();
        String month = DateUtil.format(DateUtil.date(), "yyyy-MM");
        LambdaQueryWrapper<By01MaintenanceSchedule> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(By01MaintenanceSchedule::getStationNumber1, deviceCode)
                .in(By01MaintenanceSchedule::getOtherOrganiser1, "已完成")
                .like(By01MaintenanceSchedule::getVsDate,month)
                .orderByDesc(By01MaintenanceSchedule::getVsDate);
        List<By01MaintenanceSchedule> list = by01MaintenanceScheduleMapper.selectList(wrapper);
        ScanDto.WbGzInfo wbInfo = result.getWbInfo();
        wbInfo.setTotal(list.size());
        wbInfo.getList().addAll(CollUtil.sub(list,0,6));
    }

    private void setGzInfo(ScanDto result){
        ScanDto.Info topInfo = result.getTopInfo();
        String deviceCode = topInfo.getDeviceCode();
        int year = DateUtil.date().year();
        LambdaQueryWrapper<SchedulingOfSbbx01MalfunctionRep> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SchedulingOfSbbx01MalfunctionRep::getDeviceNumber, deviceCode)
                .in(SchedulingOfSbbx01MalfunctionRep::getMaintenanceStatus, "已完成")
                .like(SchedulingOfSbbx01MalfunctionRep::getMaintenanceDate,year)
                .orderByDesc(SchedulingOfSbbx01MalfunctionRep::getMaintenanceDate);
        List<SchedulingOfSbbx01MalfunctionRep> list = schedulingOfSbbx01MalfunctionRepMapper.selectList(wrapper);
        ScanDto.WbGzInfo gzInfo = result.getGzInfo();
        gzInfo.setTotal(list.size());
        gzInfo.getList().addAll(CollUtil.sub(list,0,6));

    }

    private List<String> getBzDateList(){
        LocalDate start = LocalDate.now().minusDays(6);
        LocalDate end = LocalDate.now();
        List<String> dates = new ArrayList<>();
        while(!start.isAfter(end)){
            dates.add(start.toString());
            start = start.plusDays(1);
        }
        return dates;
    }
}
